# Performs generic (non-project specific) validation of v1 Snippet File Contents

macro(add_error error)
  string(APPEND RunCMake_TEST_FAILED "${error}\n")
endmacro()

macro(snippet_error snippet error)
  add_error("Error in snippet file ${snippet}:\n${error}")
endmacro()

macro(has_key snippet json key)
  string(JSON data ERROR_VARIABLE missingKey GET "${json}" ${key})
  if (NOT ${missingKey} MATCHES NOTFOUND)
    snippet_error(${snippet} "Missing ${key}")
  endif()
endmacro()

macro(has_not_key snippet json key)
  string(JSON data ERROR_VARIABLE missingKey GET "${json}" ${key})
  if (${missingKey} MATCHES NOTFOUND)
    snippet_error(${snippet} "Has unexpected ${key}")
  endif()
endmacro()

macro(snippet_has_fields snippet contents)
  get_filename_component(filename ${snippet} NAME)
  has_key(${snippet} ${contents} command)
  has_key(${snippet} ${contents} role)
  has_key(${snippet} ${contents} result)
  if (filename MATCHES ^link-*)
    has_key(${snippet} ${contents} target)
    has_key(${snippet} ${contents} outputs)
    has_key(${snippet} ${contents} outputSizes)
    has_key(${snippet} ${contents} targetType)
    has_key(${snippet} ${contents} targetLabels)
  elseif (filename MATCHES ^compile-*)
    has_key(${snippet} ${contents} target)
    has_key(${snippet} ${contents} outputs)
    has_key(${snippet} ${contents} outputSizes)
    has_key(${snippet} ${contents} source)
    has_key(${snippet} ${contents} language)
  elseif (filename MATCHES ^custom-*)
    has_key(${snippet} ${contents} target)
    has_key(${snippet} ${contents} outputs)
    has_key(${snippet} ${contents} outputSizes)
  elseif (filename MATCHES ^test-*)
    has_key(${snippet} ${contents} testName)
  endif()
  if(ARGS_DYNAMIC_QUERY)
    has_key(${snippet} ${contents} dynamicSystemInformation)
    string(JSON dynamicSystemInfo ERROR_VARIABLE noInfo GET "${contents}" dynamicSystemInformation)
    if (noInfo MATCHES NOTFOUND)
      has_key(${snippet} ${dynamicSystemInfo} beforeCPULoadAverage)
      has_key(${snippet} ${dynamicSystemInfo} beforeHostMemoryUsed)
      has_key(${snippet} ${dynamicSystemInfo} beforeCPULoadAverage)
      has_key(${snippet} ${dynamicSystemInfo} beforeHostMemoryUsed)
    endif()
  else()
    has_not_key(${snippet} ${contents} dynamicSystemInformation)
    string(JSON dynamicSystemInfo ERROR_VARIABLE noInfo GET "${contents}" dynamicSystemInformation)
    if (noInfo MATCHES NOTFOUND)
      has_not_key(${snippet} ${dynamicSystemInfo} beforeCPULoadAverage)
      has_not_key(${snippet} ${dynamicSystemInfo} beforeHostMemoryUsed)
      has_not_key(${snippet} ${dynamicSystemInfo} beforeCPULoadAverage)
      has_not_key(${snippet} ${dynamicSystemInfo} beforeHostMemoryUsed)
    endif()
  endif()
endmacro()

macro(snippet_valid_timing contents)
  string(JSON start GET "${contents}" timeStart)
  string(JSON duration GET "${contents}" duration)
  if (${start} LESS 0)
    snippet_error(${snippet} "Negative time start: ${start}")
  endif()
  if (${duration} LESS 0)
    snippet_error(${snippet} "Negative duration: ${end}")
  endif()
endmacro()

macro(verify_snippet snippet contents)
  snippet_has_fields(${snippet} ${contents})
  snippet_valid_timing(${contents})
  string(JSON version GET "${contents}" version)
  if (NOT ${version} EQUAL 1)
    snippet_error(${snippet} "Version must be 1, got: ${version}")
  endif()
  string(JSON role GET "${contents}" role)
  get_filename_component(filename ${snippet} NAME)
  if (NOT ${filename} MATCHES ^${role}-)
    snippet_error(${snippet} "Role \"${role}\" doesn't match snippet filename")
  endif()
  string(JSON outputs ERROR_VARIABLE noOutputs GET "${contents}" outputs)
  if (NOT outputs MATCHES NOTFOUND)
    string(JSON outputSizes ERROR_VARIABLE noOutputSizes GET "${contents}" outputSizes)
    list(LENGTH outputs outputsLen)
    list(LENGTH outputSizes outputSizesLen)
    if (outputSizes MATCHES NOTFOUND OR NOT outputsLen EQUAL outputSizesLen)
      snippet_error(${snippet} "outputs and outputSizes do not match")
    endif()
  endif()
endmacro()
